home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Audio / Spectro / Source / Spectro.m < prev    next >
Text File  |  1994-05-06  |  16KB  |  506 lines

  1.  
  2. /* Generated by Interface Builder */
  3.  
  4. #import "Spectro.h"
  5. #import "SpectrumView.h"
  6. #import "WaterfallView.h"
  7. #import "WaterfallComputer.h"
  8. #import "SignalProcessor.h"
  9. #import <appkit/appkit.h>
  10. #import <soundkit/soundkit.h>
  11. #import <math.h>
  12. #import <string.h>
  13. #import <stdio.h>
  14.  
  15. int data_size,power_of_four,window_size,num_frames,total_data,s_rate,mono_file;
  16. float f[16384],freq_max;
  17. BOOL running_analysis = FALSE,one_time = FALSE,waterfall = FALSE;
  18. char window_type[200];
  19. int firstSample,sampleCount;
  20. float ceiling,flor;
  21.  
  22. @implementation Spectro
  23.  
  24. - changeFreqMax:sender
  25. {
  26.     int i;
  27.     freq_max = [[sender cellAt: 0 : 4] floatValue];
  28.     if (freq_max>0.5*s_rate) freq_max = 0.5 * s_rate;
  29.     for (i=1;i<5;i++) {
  30.         [[freqRange cellAt: 0 : i] setIntValue:  i * 0.25 * freq_max];
  31.         [[freqRange2 cellAt: 0 : i] setIntValue:  i * 0.25 * freq_max];
  32.     }
  33.     [myView setFreqRange: freq_max andAmpRange: [myView ampRange]];
  34.     [myView clear];
  35.     [myView placeVerticals: 0.25];
  36.     [self calculate:nil];
  37.     return self;
  38. }
  39.  
  40. - selectionChanged:sender
  41. {
  42.     mySound = [sender sound];
  43.     [mySound compactSamples];
  44.     [self setup: sender];
  45.     if ([goOnSelect state]) [self calculate:self];
  46.     return self;
  47. }
  48.  
  49. - setup:sender
  50. {
  51.     int i;
  52.     [[soundView docView] getSelection:&firstSample size:&sampleCount];
  53.     if ((firstSample + sampleCount)>[[[soundView docView] sound] sampleCount])    sampleCount = [[[soundView docView] sound] sampleCount] - firstSample;
  54.     num_frames = sampleCount / [windowSize intValue] * 2 - 1;
  55.     if (num_frames<1) num_frames = 0;
  56.     s_rate = [mySound samplingRate];
  57.     [numFrames setIntValue: num_frames];
  58.     freq_max = [[freqRange cellAt: 0 : 4] floatValue];
  59.     if (freq_max>0.5*s_rate) freq_max = 0.5 * s_rate;
  60.     for (i=1;i<5;i++) {
  61.         [[freqRange cellAt: 0 : i] setIntValue:  i * 0.25 * freq_max];
  62.         [[freqRange2 cellAt: 0 : i] setIntValue:  i * 0.25 * freq_max];
  63.     }
  64.     flor = [[viewLimit cellAt: 4: 0] floatValue];
  65.     [myView setFreqRange: freq_max andAmpRange: flor];
  66.     [beginTime setDoubleValue: (double) firstSample / s_rate];
  67.     [self changeTimeSetups: numFrames]; 
  68.     return self;
  69. }
  70.  
  71. - calculate:sender
  72. {
  73. //    int temp_num_frames;
  74. //    mySound = [[soundView docView] sound];
  75. //    [mySound compactSamples];
  76. //    temp_num_frames = [mySound sampleCount] / [windowSize intValue] * 2 - 1;
  77. //    num_frames = [numFrames intValue];
  78. //    if (temp_num_frames < num_frames)    {
  79. //        num_frames = temp_num_frames;
  80. //    [numFrames setIntValue: num_frames];
  81. //        [self changeTimeSetups: numFrames]; 
  82. //    }
  83.     one_time = TRUE;
  84.     [self doSpectrum];
  85.     one_time = FALSE;
  86.     return self;
  87. }
  88.  
  89. - knockItOff:sender
  90. {
  91.     one_time = FALSE;
  92.     return self;
  93. }
  94.  
  95. - (int) passThisToWFViewPlease:  (float *) f     // this is sent by WaterfallComputer to draw views
  96. {            // It's here so later we can put the computation into a different thread
  97.             // We're faking that now by checking the stop button explicitly each time.
  98.     NXRect buttonBounds;
  99.     NXPoint mousePosition;
  100.     int mouseDown,windowIsKey;
  101.     [myWaterfallView drawNext: f];
  102.     [[stopButton window] getMouseLocation: &mousePosition];
  103.     [stopButton getBounds: &buttonBounds];
  104.     PSbuttondown(&mouseDown);
  105. //    windowIsKey = [[stopButton window] isKeyWindow];
  106.     if ([stopButton mouse:&mousePosition inRect: &buttonBounds] && mouseDown) return 1;
  107.     else return 0;
  108. }
  109.  
  110.  
  111. - doSpectrum
  112. {
  113.     float temp_f[16384];
  114.     int i;
  115.     float timeDelta,timeBegin;
  116.     unsigned char *data;
  117.     short *linear_data;
  118.     mySound = [[soundView docView] sound];
  119.     if (mySound)     {
  120.       [mySound compactSamples];
  121.       [[soundView docView] getSelection:&firstSample size:&sampleCount];
  122.       if ((firstSample + sampleCount)>[[[soundView docView] sound] sampleCount])    
  123.           sampleCount = [[[soundView docView] sound] sampleCount] - firstSample;
  124.       data = [mySound data];
  125.       linear_data = (short *) data;
  126.       strcpy(window_type,[windowType stringValue]);
  127.       flor = [[viewLimit cellAt: 4: 0] floatValue];
  128.       ceiling = 2.0 * 65536.0 * 65536.0 * window_size;
  129.       mono_file = 2;
  130.       if  ([mySound channelCount]>1)     {
  131.         mono_file = NXRunAlertPanel("Spectro is Confused","The current sound is stereo.\
  132.     What should I transform?","Both Mixed","Right","Left");
  133.     printf("%i\n",mono_file);
  134.      }
  135.       if (num_frames>1 && one_time)    {
  136.     for (i=0;i<data_size;i++) temp_f[i] = f[i];
  137.     if (!myWaterfallComputer)     {
  138.         myWaterfallComputer = [[WaterfallComputer allocFromZone:[self zone]] init];
  139.         [myWaterfallComputer setSignalProcessor: mySignalProcessor];
  140.         [myWaterfallComputer setApp: self];
  141.     }
  142.     [myWaterfallView setup: num_frames length: (int) (data_size * freq_max / s_rate)];
  143.     if ([mySound dataFormat]==1)    
  144.         [myWaterfallComputer computeThisCodex: data];
  145.     else
  146.         [myWaterfallComputer computeThisLinear: linear_data];
  147.         timeDelta = ([totalSeconds floatValue] / num_frames) * (num_frames + 1) * 0.25;
  148.         timeBegin = [beginTime floatValue];
  149.         for (i=0;i<5;i++)    {
  150.             [[wfTimes cellAt: 4-i : 0] setFloatValue: timeBegin];
  151.         timeBegin += timeDelta;
  152.         }
  153.     [myView clear];
  154.     [frameSlider setFloatValue: 0.0];
  155.          [self sliderChange: frameSlider];
  156.     [myView placeVerticals: 0.25];
  157.     [myView drawSpectrum: (int) (data_size * freq_max / s_rate) array: f];
  158.     s_rate = [mySound samplingRate];
  159.     if (freq_max==0)  freq_max = 0.5 * s_rate;
  160.     for (i=1;i<5;i++) {
  161.         [[freqRange cellAt: 0 : i] setIntValue:  i * 0.25 * freq_max];
  162.         [[freqRange2 cellAt: 0 : i] setIntValue:  i * 0.25 * freq_max];
  163.     }
  164.     [myView setFreqRange: freq_max andAmpRange: flor];
  165.     [myView placeHorizontals: 0.25];
  166.       }
  167.       else {
  168.     for (i=0;i<data_size;i++) temp_f[i] = f[i];
  169.     if ([mySound dataFormat]==1)
  170.         for (i=0;i<window_size;i++) f[i] = (float) SNDiMulaw(data[i + firstSample]);
  171.     else    {
  172.         if (mono_file==2)
  173.             for (i=0;i<window_size;i++) f[i] = (float) linear_data[i +firstSample];
  174.         if (mono_file==1)
  175.             for (i=0;i<window_size;i++) f[i] = (float) (linear_data[2*(i +firstSample)] + 
  176.                                         linear_data[2*(i + firstSample) + 1]) * 0.5;
  177.         if (mono_file==0)
  178.             for (i=0;i<window_size;i++) f[i] = (float) linear_data[2*(i + firstSample) + 1];
  179.         if (mono_file==-1)
  180.             for (i=0;i<window_size;i++) f[i] = (float) linear_data[2*(i + firstSample)];
  181.     }
  182.     for (i=window_size;i<data_size;i++) f[i] = 0.0;
  183.     [mySignalProcessor window: window_size array: f type: window_type phase: FALSE];
  184.     [mySignalProcessor fhtRX4: power_of_four array: f];
  185.     [mySignalProcessor logMag: data_size array: f floor: flor ceiling: ceiling];
  186.     [myView drawSpectrum: (int) (data_size * freq_max / s_rate) array: temp_f erase: TRUE];
  187.     [myView placeVerticals: 0.25];
  188.     [myView drawSpectrum: (int) (data_size * freq_max / s_rate) array: f];
  189.     s_rate = [mySound samplingRate];
  190.     if (freq_max==0)  freq_max = 0.5 * s_rate;
  191.         for (i=1;i<5;i++) {
  192.         [[freqRange cellAt: 0 : i] setIntValue:  i * 0.25 * freq_max];
  193.         [[freqRange2 cellAt: 0 : i] setIntValue:  i * 0.25 * freq_max];
  194.     }
  195.     [myView setFreqRange: freq_max  andAmpRange: flor];
  196.     [myView placeHorizontals: 0.25];
  197.       }
  198.     }
  199.     return self;
  200. }
  201.  
  202. - changeZPFactor: sender
  203. {
  204.     double temp;
  205.     window_size = [windowSize intValue];
  206.     data_size = window_size * [zpFactor floatValue];
  207.     num_frames = [numFrames intValue];
  208.     temp = log((double) data_size) / log(4.0);
  209.     if (temp>7.0) temp=7.0;
  210.     power_of_four = temp + .999;
  211.     data_size = pow(4.0,power_of_four);
  212.     [zpFactor setFloatValue: ((float) data_size / (float) window_size)];
  213.     if (s_rate>0)    temp = (float) window_size / (float) s_rate * 0.5;
  214.     [hopTime setDoubleValue: temp];
  215.     [windowTime setDoubleValue: temp * 2.0];
  216.     [totalSeconds setDoubleValue: temp * [numFrames doubleValue]];
  217.     [self setup: self];
  218.     [self calculate: self];
  219.     return self;
  220. }
  221.  
  222. - changeWindowSize:sender
  223. {
  224.     [zpFactor setIntValue: 1];
  225.     [myView clear];
  226.     [self setup:self];
  227.     [self calculate:self];
  228.     return self;
  229. }
  230.  
  231. - changeTimeSetups: sender
  232. {
  233.     double temp;
  234.     window_size = [windowSize intValue];
  235.     data_size = window_size * [zpFactor floatValue];
  236.     num_frames = [numFrames intValue];
  237.     temp = log((double) data_size) / log(4.0);
  238.     if (temp>7.0) temp=7.0;
  239.     power_of_four = temp + .999;
  240.     data_size = pow(4.0,power_of_four);
  241.     [zpFactor setFloatValue: ((float) data_size / (float) window_size)];
  242.     mySound = [[soundView docView] sound];
  243.     s_rate = [mySound samplingRate];
  244.     if (s_rate>0)    temp = (float) window_size / (float) s_rate* 0.5;
  245.     [hopTime setDoubleValue: temp];
  246.     [windowTime setDoubleValue: temp * 2.0];
  247.     [totalSeconds setDoubleValue: temp * [numFrames doubleValue]];
  248.     return self;
  249. }
  250.  
  251. - changeViewLimit:sender
  252. {
  253.     int temp,i;
  254.     temp = [sender intValue];
  255.     if (temp>0) temp = -temp;
  256.     for (i=0;i<4;i++)  [[viewLimit cellAt: i : 0] setIntValue: temp * i / 4];
  257.     [myView clear];
  258.     s_rate = [mySound samplingRate];
  259.     if (freq_max==0)     freq_max = 0.5 * s_rate;
  260.     for (i=1;i<5;i++) {
  261.         [[freqRange cellAt: 0 : i] setIntValue:  i * 0.25 * freq_max];
  262.         [[freqRange2 cellAt: 0 : i] setIntValue:  i * 0.25 * freq_max];
  263.     }
  264.     [myView setFreqRange: freq_max  andAmpRange: temp];
  265.     [self calculate:nil];
  266.     return self;
  267. }
  268.  
  269. - timeChange:sender
  270. {
  271.     float temp;
  272.     int plot;
  273.     temp = [sender floatValue] - [beginTime floatValue];
  274.     plot = temp / [hopTime floatValue];
  275.     temp = plot /  ([numFrames floatValue]);
  276.     [frameSlider setFloatValue: temp];
  277.     [self sliderChange: frameSlider];
  278.     return self;
  279. }
  280.  
  281. - frameChange:sender
  282. {
  283.     float temp;
  284.     int plot;
  285.     plot = [sender intValue];
  286.     temp = plot /  (1.5 + [numFrames floatValue]);
  287.     [frameSlider setFloatValue: temp];
  288.     [self sliderChange: frameSlider];
  289.     return self;
  290. }
  291.  
  292. - sliderChange:sender
  293. {
  294.     float temp,temp_f[17000];
  295.     int plot,k,i;
  296.     unsigned char *data;
  297.     short *linear_data;
  298.     mySound = [[soundView docView] sound];
  299.     if (mySound)    {
  300.     [mySound compactSamples];
  301.     [[soundView docView] getSelection:&firstSample size:&sampleCount];
  302.     if ((firstSample + sampleCount)>[[[soundView docView] sound] sampleCount])        sampleCount = [[[soundView docView] sound] sampleCount] - firstSample;
  303.     data = [mySound data];
  304.     linear_data = (short *) data;
  305.     strcpy(window_type,[windowType stringValue]);
  306.     flor = [[viewLimit cellAt: 4: 0] floatValue];
  307.     ceiling = 2.0 * 65536.0 * 65536.0 * window_size;
  308.     temp = [sender floatValue];
  309.     plot = temp * (2.5 + [numFrames floatValue]);
  310.     [currentTime setFloatValue: [hopTime floatValue] * plot + [beginTime floatValue]];
  311.     [currentPlot setIntValue: plot];
  312.     if (plot > [numFrames intValue] - 1) plot = [numFrames intValue]  - 1;
  313.     [myWaterfallView placeTickAt: plot];
  314.     for (i=0;i<data_size;i++) temp_f[i] = f[i];
  315.     [myView drawSpectrum: (int) (data_size * freq_max / s_rate) array: temp_f erase: TRUE];
  316.     k = plot * window_size * 0.5;
  317.     if ([mySound dataFormat]==1)    
  318.         for (i=0;i<window_size;i++) f[i] = (float) SNDiMulaw(data[i +k + firstSample]);
  319.         else    {
  320.         if (mono_file==2)
  321.         for (i=0;i<window_size;i++) f[i] = (float) linear_data[i +k+ firstSample];
  322.         if (mono_file==1)
  323.         for (i=0;i<window_size;i++) f[i] = (float) (linear_data[2*(i +k+ firstSample)] + 
  324.                                         linear_data[2*(i + k+ firstSample) + 1]) * 0.5;
  325.         if (mono_file==0)
  326.         for (i=0;i<window_size;i++) f[i] = (float) linear_data[2*(i + k+ firstSample) + 1];
  327.         if (mono_file==-1)
  328.         for (i=0;i<window_size;i++) f[i] = (float) linear_data[2*(i +k+ firstSample)];
  329.         }
  330.     for (i=window_size;i<data_size;i++) f[i] = 0.0;
  331.     [mySignalProcessor window: window_size array: f type: window_type phase: FALSE];
  332.     [mySignalProcessor fhtRX4: power_of_four array: f];
  333.     [mySignalProcessor logMag: data_size array: f floor: flor ceiling: ceiling];
  334.      [myView drawSpectrum: (int) (data_size * freq_max / s_rate) array: f];
  335.     [myView placeVerticals: 0.25];
  336.     [myView drawSpectrum: (int) (data_size * freq_max / s_rate) array: f];
  337.     s_rate = [mySound samplingRate];
  338.         for (i=1;i<5;i++) {
  339.         [[freqRange cellAt: 0 : i] setIntValue:  i * 0.25 * freq_max];
  340.         [[freqRange2 cellAt: 0 : i] setIntValue:  i * 0.25 * freq_max];
  341.     }
  342.     [myView setFreqRange: freq_max  andAmpRange: flor];
  343.     [myView placeHorizontals: 0.25];
  344.     }
  345.     return self;
  346. }
  347.  
  348. - running:sender
  349. {
  350.     double temp;
  351.     window_size = [windowSize intValue];
  352.     data_size = window_size * [zpFactor floatValue];
  353.     num_frames = [numFrames intValue];
  354.     temp = window_size / 16024.0;
  355.     [hopTime setDoubleValue: temp];
  356.     [windowTime setDoubleValue: temp * 2.0];
  357.     [totalSeconds setDoubleValue: temp * [numFrames doubleValue]];
  358.     temp = log((double) data_size) / log(4.0);
  359.     if (temp>7.0) temp=7.0;
  360.     power_of_four = temp + .999;
  361.     data_size = pow(4.0,power_of_four);
  362.     [zpFactor setFloatValue: ((float) data_size / (float) window_size)];
  363.     if (sender==loopButton&&[loopButton state]) [myView clear];
  364.     if ([loopButton state]) running_analysis = TRUE; else running_analysis = FALSE;
  365. //    if (sender==oneTime) one_time = TRUE;
  366.     if (running_analysis || one_time)    {
  367.         mySound = [[soundView docView] sound];
  368.     if (!mySound) {
  369.         [[soundView docView] setSound: [Sound new]];
  370.         mySound = [[soundView docView] sound];
  371.             [mySound setDelegate: self];
  372.         }
  373.     if (running_analysis)        {
  374.                 total_data = window_size;
  375.                 [mySound setDataSize: window_size
  376.                         dataFormat: SND_FORMAT_MULAW_8
  377.                         samplingRate:SND_RATE_CODEC
  378.                         channelCount: 1
  379.                         infoSize: 12];
  380.         }
  381.     [mySound record];
  382.     }
  383.     return self;
  384. }
  385.  
  386. - didRecord:sender
  387. {
  388.     if (running_analysis)    {
  389.     [self doSpectrum];
  390.     [self running: nil];
  391.     }
  392.     if (one_time) {
  393.         [soundMeter stop:self];
  394.     one_time = FALSE;
  395.     }
  396.     return self;
  397. }
  398.  
  399. - save:sender
  400. {
  401.     char file_name[200];
  402.     strcpy(file_name,[fileName stringValue]);
  403.     [[[soundView docView] sound] writeSoundfile:file_name];
  404.     return self;
  405. }
  406.  
  407. - zoomOut:sender
  408. {
  409.     [[soundView docView] setReductionFactor: [[soundView docView] reductionFactor] * 2.0];
  410.     return self;
  411. }
  412.  
  413. - zoomIn:sender
  414. {
  415.     [[soundView docView] setReductionFactor: [[soundView docView] reductionFactor] * 0.5];
  416.     return self;
  417. }
  418.  
  419. - showAll:sender
  420. {
  421.     NXRect frame;
  422.     double num_samps;
  423.     num_samps = [[[soundView docView] sound] sampleCount];
  424.     [[soundView docView] setReductionFactor: 1.0];
  425.     [[soundView docView] getVisibleRect: &frame];
  426.     [[soundView docView] setReductionFactor: num_samps / frame.size.width];
  427.     return self;
  428. }
  429.  
  430. - showSelection:sender
  431. {
  432.     NXRect frame;
  433.     int beg, size;
  434.     double num_samps;
  435.     float total_samps;
  436.     [[soundView docView] getSelection: &beg size: &size];
  437.     num_samps = size;
  438.     total_samps = (float) [[[soundView docView] sound] sampleCount];
  439.     [[soundView docView] setReductionFactor: 1.0];
  440.     [[soundView docView] getVisibleRect: &frame];
  441.     [[soundView docView] setReductionFactor: num_samps / frame.size.width];
  442.     [[soundView horizScroller] setFloatValue: (float) beg / total_samps];
  443.     [soundView display];
  444.     return self;
  445. }
  446.  
  447. - play:sender
  448. {
  449.     [[soundView docView] setDelegate: self];
  450.     [soundView play:sender];
  451.     return self;
  452. }
  453.  
  454. - stop:sender
  455. {
  456.     [soundView stop:sender];
  457.     [soundMeter stop:self];
  458.     return self;
  459. }
  460.  
  461. - record:sender
  462. {
  463.     [[soundView docView] setDelegate: self];
  464.     [soundView record:sender];
  465.     return self;
  466. }
  467.  
  468. - willPlay:sender
  469. {
  470.     [soundMeter setSound: [[soundView docView] soundBeingProcessed]];
  471.     [soundMeter run:self];
  472.     return self;
  473. }
  474.  
  475. - willRecord:sender
  476. {
  477.     [soundMeter setSound: [[soundView docView] soundBeingProcessed]];
  478.     [soundMeter run:self];
  479.     return self;
  480. }
  481.  
  482. - didPlay:sender
  483. {
  484.     [soundMeter stop:self];
  485.     return self;
  486. }
  487.  
  488. - load:sender
  489. {
  490.     char file_name[200];
  491.     strcpy(file_name,[fileName stringValue]);
  492.     [mySound free];
  493.     if (mySound = [Sound newFromSoundfile: file_name])    {
  494.         [[soundView docView] setSound: mySound];
  495.         [[soundView docView] setDelegate: self];
  496.         [self setup:sender];
  497.     }
  498.     else    {
  499.         [mySound free];
  500.     NXRunAlertPanel("Spectro is Confused","I can't find that file.",NULL,NULL,"OK");
  501.     }
  502.     return self;
  503. }
  504.  
  505. @end
  506.